/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2004
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
*
* Author's email : insane@dees.ufmg.br
* Author's Website : http://www.dees.ufmg.br/insane
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package br.ufmg.dees.insane.model.xfemModel.xfemelementNode;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import br.ufmg.dees.insane.model.femModel.elementNode.ElementNode;
import br.ufmg.dees.insane.model.femModel.node.Node;
import br.ufmg.dees.insane.model.xfemModel.enrichmentItem.CrackInterior;
import br.ufmg.dees.insane.model.xfemModel.enrichmentItem.EnrichmentItem;
import br.ufmg.dees.insane.model.xfemModel.xfemElement.XFEMElement;

/**
 * @author Kelson Wolff
 *
 */
public class XFEMElementNode extends ElementNode {
	
	private static final long serialVersionUID = 1L;
	
	/** List of elements that hold this Node. */
	protected List<XFEMElement> elementsThatIbelongTo;
	
	/**
	 * The List of Enrichment Items that enrich this XFEMElementNode.
	 */
	protected List<EnrichmentItem> enrichmentItemListOfNode;
	
	/**
	 * The parameter that holds "1" if this XFEMElementNode is
	 * enriched and "0" if this XFEMElementNode isn't enriched
	 * with anyone Enrichment Item.
	 */
	protected int isEnriched;
	
	protected boolean isUpdated;

	/**
	 * @param n
	 */
	public XFEMElementNode(Node n) {
		super(n);
		// TODO Auto-generated constructor stub
		this.elementsThatIbelongTo = new ArrayList<XFEMElement>();
		this.label = n.getLabel();
		this.isEnriched = 0;
		this.isUpdated = false;
		this.enrichmentItemListOfNode = new ArrayList<EnrichmentItem>();
	}

	/**
	 * 
	 */
	public XFEMElementNode() {
		super();
		// TODO Auto-generated constructor stub
		this.elementsThatIbelongTo = new ArrayList<XFEMElement>();
		this.isEnriched = 0;
		this.isUpdated = false;
		this.enrichmentItemListOfNode = new ArrayList<EnrichmentItem>();
	}
	
	/**
	 * @return Returns the elementsThatIbelongTo.
	 */
	public List<XFEMElement> getElementsThatIbelongTo() {
		return this.elementsThatIbelongTo;
	}

	/**
	 * @param elementsThatIbelongTo The elementsThatIbelongTo to set.
	 */
	public void setElementsThatIbelongTo(XFEMElement element) {
		this.elementsThatIbelongTo.add(element);
	}
	
	/**
	 * @return Returns the isUpdated.
	 */
	public boolean isUpdated() {
		return isUpdated;
	}

	/**
	 * @param isUpdated The isUpdated to set.
	 */
	public void setUpdated(boolean isUpdated) {
		this.isUpdated = isUpdated;
	}
	
	/**
	 * Sets true to isUpdated.
	 */
	public void setIsUpdated(){
		this.isUpdated = true;
	}

	/**
	 * @return Returns the isEnriched.
	 */
	public int getIsEnriched() {
		return isEnriched;
	}

	/**
	 * @param isEnriched The isEnriched to set.
	 */
	public void setIsEnriched(int isEnriched) {
		this.isEnriched = isEnriched;
	}

	/**
	 * @return Returns the enrichmentItemListOfNode.
	 */
	public List<EnrichmentItem> getEnrichmentItemListOfNode() {
		return enrichmentItemListOfNode;
	}

	/**
	 * @param enrichmentItemListOfNode The enrichmentItemListOfNode to set.
	 */
	public void setEnrichmentItemListOfNode(List<EnrichmentItem> enrichmentItemListOfNode) {
		this.enrichmentItemListOfNode = enrichmentItemListOfNode;
	}
	
	/**
	 * Adds the provided enrichmentItem at the List of
	 * Enrichment Items that belong to this XFEMElementNode.
	 * @param enrichmentItem The provided Enrichment Item.
	 */
	public void setEnrichmentItemListOfNode(EnrichmentItem enrichmentItem) {
		this.enrichmentItemListOfNode.add(enrichmentItem);
	}

	/**
	 * Clears the List of Enrichment Items
	 * that belong to this XFEMElementNode.
	 */
	public void eraseListOfEnrichmentItems(){
		this.enrichmentItemListOfNode.clear();
	}
	
	/**
	 * Verifies if the list of Enrichment Items of this Node contains both 
	 * a CrackTip and a CrackInterior then remove the CrackInterior
	 * from the list.
	 */
	public void resolveConflictsInEnrichment(){
		
	}
	
	/**
	 * Returns true if this XFEMElementNode is enriched by the step function
	 * and false if it isn't.
	 * @return True if this XFEMElementNode is enriched by the step function
	 * and false if it isn't.
	 */
	public boolean isStepEnriched(){
		if(this.getIsEnriched() == 0){
			return false;
		}
		int itEnrItem = 0;
		int itEnd = this.getEnrichmentItemListOfNode().size();
		ListIterator liEnrItem = this.getEnrichmentItemListOfNode().listIterator();
		while(liEnrItem.hasNext()){
			EnrichmentItem eItem = (EnrichmentItem) liEnrItem.next();
			if(eItem instanceof CrackInterior){
				itEnrItem = itEnrItem + 1;
			}
		}
		return ((itEnrItem != itEnd) ? true : false);	
	}
	
	/**
	 * If this XFEMElementNode is enriched with Enrichment Item enrItem, 
	 * then insert enrItem into the list of Enrichment Items.
	 * Also sets member isEnriched equals to 1.
	 * @param enrItem The provided Enrichment Item.
	 */
	public void isEnrichedWith(EnrichmentItem enrItem){
		if(this.enrichmentItemListOfNode == null){
			this.enrichmentItemListOfNode = new ArrayList<EnrichmentItem>();
		}
		ListIterator liEnrItem = this.getEnrichmentItemListOfNode().listIterator(this.getEnrichmentItemListOfNode().indexOf(enrItem));
		ListIterator liEnd = this.getEnrichmentItemListOfNode().listIterator(this.getEnrichmentItemListOfNode().size() - 1);
		if(liEnrItem == liEnd){
			this.enrichmentItemListOfNode.add(enrItem);
		}
		this.setIsEnriched(1);
		
		//this->domain->setEnrichedNodesList(this);
	}
	
	/**
	 * 
	 * @param enrItem The provided Enrichment Item.
	 */
	public void resolveLinearDependency(EnrichmentItem enrItem){
//		00498 // Using the area inclusion criterion to remove discontinuous enriched nodes
//		00499 // NVP 2005-06-04
//		00500 {
//		00503   double eps = 0.0001 ;
//		00504   
//		00505   // get the support of this Node from the Domain
//		00506   map<Node*,vector<Element*> > nodeElemMap = this->domain->giveNodalSupports();
//		00507   vector<Element*>  mySupport = nodeElemMap[this] ; 
//		00508 
//		00509   double A   = 0.0 ;   // A is the area of the support
//		00510   double A1  = 0.0 ;   // the area above the CrackInterior
//		00511   double temp = 0.0 ;
//		00512 
//		00513   vector<Element*>* elemList = enrItem->giveElementsInteractWithMe(); 
//		00514   vector<Element*> :: iterator iter ;
//		00515   // Loop on elements in nodal support, say e. If e intersects with enrItem, then
//		00516   // compute the area of e above enrItem by e->giveAreaAboveEnrItem() ;
//		00517   for(size_t i = 0 ; i < mySupport.size() ; i++)
//		00518   {
//		00519          A  += mySupport[i]->area();
//		00520          iter = find(elemList->begin(),elemList->end(),mySupport[i]); 
//		00521          if (iter != elemList->end()) 
//		00522          {
//		00523                 A1 += mySupport[i]->computeAreaAboveEnrItem(enrItem); // area of part of element above the enrItem
//		00524                 temp += mySupport[i]->area() ; // area of elements in nodal support which are split by the crack
//		00525          }
//		00526   }
//		00527   GeometryEntity *geoOfEnrItem = enrItem->giveMyGeo() ;
//		00528   Mu::Point *p = this->makePoint() ;
//		00529   int check = geoOfEnrItem->givePositionComparedTo(p);
//		00530 
//		00531   if(check == 1)       // node is above the crack 
//		00532          A1 += A - temp ;
//		00533   double A2 = A - A1 ; // the area below the Crack
//		00534 
//		00535   // finally the area inclusion criteria is applied
//		00536   if ((A1/A < eps) || (A2/A < eps))
//		00537   {
//		00538          enrichmentItemListOfNode->remove(enrItem); //do not enrich this node with H(x) any more 
//		00539          // after being removed enrichment, if enrichmentItemListOfNode does not contain any
//		00540          // enrichment item, then this node is a classical node !!! NVP 2005-07-12 
//		00541          if(enrichmentItemListOfNode->size() == 0 )
//		00542          {
//		00543                 isEnriched = 0 ;
//		00544                 // update the enriched-nodes-list of DOMAIN !!!
//		00545                 this->domain->removeNodeFromEnrichedNodesList(this); 
//		00546          }
//		00547   }
//		00548 
//		00549   delete p ;
//		00550   /*
//		00551   // ------------------------- DEBUG --------------------------------------------
//		00552   std::cout<< " checking node " << number << " " << std::endl ;
//		00553   std::cout<< " The first  ratio  :     " << A1/A    << std::endl;
//		00554   std::cout<< " The second ratio  :     " << A2/A   << std::endl;
//		00555   // ----------------------------------------------------------------------------
//		00556   */
//		00557 }
	}

}
